Skip to content

Improve markApplicationEventSubmitted - #3987

Closed
steven-tey wants to merge 1 commit into
mainfrom
update-application-event
Closed

Improve markApplicationEventSubmitted#3987
steven-tey wants to merge 1 commit into
mainfrom
update-application-event

Conversation

@steven-tey

@steven-tey steven-tey commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Re-enabled "Source" column in partner applications to show each application's referral source.
    • Referral source now appears inline on partner info cards next to application timestamps.
  • Bug Fixes / Reliability

    • Submission recording improved to more reliably capture partner network status and submission outcomes, reducing silent failures.

@vercel

vercel Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dub Ready Ready Preview Jun 4, 2026 10:53pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR passes partner network status through application event submission, refactors markApplicationEventSubmitted to find and update a single event (with conditional referralSource rewrite), updates callers to send partnerNetworkStatus, and renders referral source in the applications table and partner info cards.

Changes

Partner Application Referral Source Tracking and Display

Layer / File(s) Summary
Application event submission with network status
apps/web/lib/application-events/update-application-event.ts
markApplicationEventSubmitted now accepts programEnrollment and a partnerNetworkStatus option, uses findUnique then update with try/catch, sets submittedAt, partnerId, and programApplicationId, and conditionally rewrites referralSource from "marketplace" to "direct" when network status is not "approved" or "trusted".
Integrate network status into application submission
apps/web/lib/actions/partners/create-program-application.ts, apps/web/lib/partners/complete-program-applications.ts
Call sites updated to pass partner.networkStatus as the partnerNetworkStatus option to markApplicationEventSubmitted.
Display referral source in partner UI
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsx, apps/web/ui/partners/partner-info-cards.tsx
Re-enables the "Source" column in the applications table and renders PartnerApplicationSource; partner info cards now show the referral source inline with the "Applied" timestamp when present.

Sequence Diagram

sequenceDiagram
  participant ProgramCreation as Program<br/>Application Flow
  participant EventService as markApplication<br/>EventSubmitted
  participant Database as programApplication<br/>Event DB
  participant UI as Referral Source<br/>Display

  ProgramCreation->>EventService: Pass programEnrollment + partnerNetworkStatus
  EventService->>Database: findUnique event by id or (programId, partnerId)
  alt Event exists
    Database-->>EventService: Return event record
    EventService->>EventService: Check: referralSource = "marketplace" && networkStatus not approved/trusted?
    alt Rewrite needed
      EventService->>Database: update with referralSource = "direct"
    else Keep existing
      EventService->>Database: update with submittedAt
    end
  else No event
    Database-->>EventService: null
    EventService->>EventService: Log and return
  end
  Database-->>UI: Event with resolved referralSource
  UI->>UI: Render PartnerApplicationSource component
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • dubinc/dub#3984: Modifies the program partners applications UI to display the "Source" column using applicationEvent?.referralSource and PartnerApplicationSource rendering.
  • dubinc/dub#3925: Touches programApplicationEvent.referralSource for referring-partner attribution; related to how referral sources are set and consumed.

Suggested reviewers

  • pepeladeira

Poem

🐰 I hopped through code to find the source,
Network status guiding the right course,
Marketplace whispers now sometimes direct,
Tables and cards show where users came next,
A tiny rabbit cheers this tracked discourse!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change—refactoring and improving the markApplicationEventSubmitted function, which is the core modification across multiple files in this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch update-application-event

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@steven-tey

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/web/lib/application-events/update-application-event.ts (1)

52-57: 💤 Low value

Use constant for referral source literals.

The code uses string literals "marketplace" and "direct" directly. The codebase defines MARKETPLACE_REFERRAL_SOURCE = "marketplace" in apps/web/lib/application-events/utils.ts. For consistency and maintainability, import and use this constant (and consider defining a DIRECT_REFERRAL_SOURCE constant as well).

♻️ Proposed refactor
+import { getApplicationEventCookieName, MARKETPLACE_REFERRAL_SOURCE } from "./utils";
-import { getApplicationEventCookieName } from "./utils";
+
+const DIRECT_REFERRAL_SOURCE = "direct";

Then update the condition:

-        ...(applicationEvent.referralSource === "marketplace" &&
+        ...(applicationEvent.referralSource === MARKETPLACE_REFERRAL_SOURCE &&
         !["approved", "trusted"].includes(partnerNetworkStatus)
           ? {
-              referralSource: "direct",
+              referralSource: DIRECT_REFERRAL_SOURCE,
             }
           : {}),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/application-events/update-application-event.ts` around lines 52
- 57, Replace the string literals "marketplace" and "direct" with shared
constants: import MARKETPLACE_REFERRAL_SOURCE from
apps/web/lib/application-events/utils.ts and add/consume a
DIRECT_REFERRAL_SOURCE constant there (e.g., export const DIRECT_REFERRAL_SOURCE
= "direct"); then update the conditional in update-application-event.ts to
compare applicationEvent.referralSource === MARKETPLACE_REFERRAL_SOURCE and to
set referralSource: DIRECT_REFERRAL_SOURCE when the condition matches; keep the
existing partnerNetworkStatus check and object spread logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/web/lib/application-events/update-application-event.ts`:
- Around line 52-57: Replace the string literals "marketplace" and "direct" with
shared constants: import MARKETPLACE_REFERRAL_SOURCE from
apps/web/lib/application-events/utils.ts and add/consume a
DIRECT_REFERRAL_SOURCE constant there (e.g., export const DIRECT_REFERRAL_SOURCE
= "direct"); then update the conditional in update-application-event.ts to
compare applicationEvent.referralSource === MARKETPLACE_REFERRAL_SOURCE and to
set referralSource: DIRECT_REFERRAL_SOURCE when the condition matches; keep the
existing partnerNetworkStatus check and object spread logic unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 96decfcd-3e5a-4504-b7ca-4e85f232af2a

📥 Commits

Reviewing files that changed from the base of the PR and between 8c854a4 and 0f10499.

📒 Files selected for processing (5)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsx
  • apps/web/lib/actions/partners/create-program-application.ts
  • apps/web/lib/application-events/update-application-event.ts
  • apps/web/lib/partners/complete-program-applications.ts
  • apps/web/ui/partners/partner-info-cards.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/lib/application-events/update-application-event.ts`:
- Around line 28-40: The current lookup returns early if
prisma.programApplicationEvent.findUnique with applicationEventId yields no row,
skipping the fallback (programId_partnerId) lookup; update
markApplicationEventSubmitted so that when applicationEventId was provided but
findUnique returns null, it performs a second findUnique using {
programId_partnerId: { programId, partnerId } } before returning. In other
words, keep the initial attempt with applicationEventId (the call to
prisma.programApplicationEvent.findUnique), and if that result is null and
applicationEventId was present, run the fallback query for the (programId,
partnerId) composite key and only return/log when both queries fail.
- Around line 44-59: The current prisma.programApplicationEvent.update call
rewrites submittedAt and may reapply referralSource changes on retries; change
the DB write to enforce the one-way transition by adding submittedAt: null to
the where clause (e.g., use updateMany or an update with that predicate) so the
update only succeeds when submittedAt is still null, and keep the existing data
payload (submittedAt: new Date(), partnerId, programApplicationId, and the
conditional referralSource rewrite) so it remains idempotent under
retries/concurrency; after switching to updateMany, handle the returned count
(zero means the transition was already applied) if the caller needs to know.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d64e6c1e-604e-4535-b062-4befd417777d

📥 Commits

Reviewing files that changed from the base of the PR and between 8c854a4 and 0f10499.

📒 Files selected for processing (5)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsx
  • apps/web/lib/actions/partners/create-program-application.ts
  • apps/web/lib/application-events/update-application-event.ts
  • apps/web/lib/partners/complete-program-applications.ts
  • apps/web/ui/partners/partner-info-cards.tsx

Comment on lines +28 to +40
const applicationEvent = await prisma.programApplicationEvent.findUnique({
where: {
...(applicationEventId
? { id: applicationEventId }
: { programId_partnerId: { programId, partnerId } }),
},
});

if (!applicationEvent) {
console.error(
"[markApplicationEventSubmitted]: No application event found, skipping...",
);
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fallback lookup is skipped when cookie ID is stale.

If applicationEventId exists but resolves to no row, the function returns early and never attempts the (programId, partnerId) unique lookup. That drops valid submission tracking for stale/deleted cookie IDs.

🔧 Proposed fix
-  const applicationEvent = await prisma.programApplicationEvent.findUnique({
-    where: {
-      ...(applicationEventId
-        ? { id: applicationEventId }
-        : { programId_partnerId: { programId, partnerId } }),
-    },
-  });
+  let applicationEvent = applicationEventId
+    ? await prisma.programApplicationEvent.findUnique({
+        where: { id: applicationEventId },
+      })
+    : null;
+
+  if (!applicationEvent && partnerId) {
+    applicationEvent = await prisma.programApplicationEvent.findUnique({
+      where: {
+        programId_partnerId: { programId, partnerId },
+      },
+    });
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/application-events/update-application-event.ts` around lines 28
- 40, The current lookup returns early if
prisma.programApplicationEvent.findUnique with applicationEventId yields no row,
skipping the fallback (programId_partnerId) lookup; update
markApplicationEventSubmitted so that when applicationEventId was provided but
findUnique returns null, it performs a second findUnique using {
programId_partnerId: { programId, partnerId } } before returning. In other
words, keep the initial attempt with applicationEventId (the call to
prisma.programApplicationEvent.findUnique), and if that result is null and
applicationEventId was present, run the fallback query for the (programId,
partnerId) composite key and only return/log when both queries fail.

Comment on lines +44 to 59
await prisma.programApplicationEvent.update({
where: {
...(applicationEventId
? { id: applicationEventId }
: { programId, partnerId }),
submittedAt: null,
id: applicationEvent.id,
},
data: {
partnerId,
submittedAt: new Date(),
partnerId,
programApplicationId: applicationId,
...(applicationEvent.referralSource === "marketplace" &&
!["approved", "trusted"].includes(partnerNetworkStatus)
? {
referralSource: "direct",
}
: {}),
},
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Submission update lost its one-way transition guard.

update() now rewrites submittedAt on every retry/re-entry. This corrupts first-submission timestamps and can reapply referral-source rewrites. Guard the transition in the DB write (submittedAt: null) so it stays idempotent under retries/concurrency.

🔒 Proposed fix
-    await prisma.programApplicationEvent.update({
-      where: {
-        id: applicationEvent.id,
-      },
-      data: {
-        submittedAt: new Date(),
-        partnerId,
-        programApplicationId: applicationId,
-        ...(applicationEvent.referralSource === "marketplace" &&
-        !["approved", "trusted"].includes(partnerNetworkStatus)
-          ? {
-              referralSource: "direct",
-            }
-          : {}),
-      },
-    });
+    const { count } = await prisma.programApplicationEvent.updateMany({
+      where: {
+        id: applicationEvent.id,
+        submittedAt: null,
+      },
+      data: {
+        submittedAt: new Date(),
+        partnerId,
+        programApplicationId: applicationId,
+        ...(applicationEvent.referralSource === "marketplace" &&
+        !["approved", "trusted"].includes(partnerNetworkStatus)
+          ? { referralSource: "direct" }
+          : {}),
+      },
+    });
+
+    if (count === 0) {
+      return;
+    }

Based on learnings: the codebase prefers enforcing state-transition preconditions directly in Prisma where clauses.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await prisma.programApplicationEvent.update({
where: {
...(applicationEventId
? { id: applicationEventId }
: { programId, partnerId }),
submittedAt: null,
id: applicationEvent.id,
},
data: {
partnerId,
submittedAt: new Date(),
partnerId,
programApplicationId: applicationId,
...(applicationEvent.referralSource === "marketplace" &&
!["approved", "trusted"].includes(partnerNetworkStatus)
? {
referralSource: "direct",
}
: {}),
},
});
const { count } = await prisma.programApplicationEvent.updateMany({
where: {
id: applicationEvent.id,
submittedAt: null,
},
data: {
submittedAt: new Date(),
partnerId,
programApplicationId: applicationId,
...(applicationEvent.referralSource === "marketplace" &&
!["approved", "trusted"].includes(partnerNetworkStatus)
? { referralSource: "direct" }
: {}),
},
});
if (count === 0) {
return;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/application-events/update-application-event.ts` around lines 44
- 59, The current prisma.programApplicationEvent.update call rewrites
submittedAt and may reapply referralSource changes on retries; change the DB
write to enforce the one-way transition by adding submittedAt: null to the where
clause (e.g., use updateMany or an update with that predicate) so the update
only succeeds when submittedAt is still null, and keep the existing data payload
(submittedAt: new Date(), partnerId, programApplicationId, and the conditional
referralSource rewrite) so it remains idempotent under retries/concurrency;
after switching to updateMany, handle the returned count (zero means the
transition was already applied) if the caller needs to know.

@steven-tey
steven-tey marked this pull request as draft June 4, 2026 23:17
@steven-tey

Copy link
Copy Markdown
Collaborator Author

closing in favor of #3988

@steven-tey steven-tey closed this Jun 4, 2026
@devkiran
devkiran deleted the update-application-event branch June 22, 2026 04:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant